﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Wormhole.Engine.Communication
{
	/// <author>Hannes Foulds</author>
	/// <date>26 September 2008</date>
	/// <summary>
	/// This class is used to dispatch events to the other player over the communication channel.
	/// </summary>
	public class Dispatcher : Listener
	{
		#region Constructor
		/// <summary>
		/// Initialize a new instance of the class.
		/// </summary>
		/// <param name="game">The game object.</param>
		/// <param name="channel">The communications channel</param>
		public Dispatcher(Wormhole.Engine.Game game, Wormhole.Engine.Communication.IClient channel)
			: base(game, channel)
		{
		}
		#endregion

		#region Initialize Game Events
		/// <summary>
		/// Wire up the events for the game object.
		/// </summary>
		protected override void InitializeGameEvents()
		{
			this.Game.GameTurn.ActionCompleted += new Wormhole.Engine.Turn.GameTurn.ActionCompleteDelegate(GameTurn_ActionCompleted);

			this.Game.Player1.KeptHand += new Wormhole.Engine.Player.Player.KeptHandDelegate(Player_KeptHand);
			this.Game.Player1.TookMulligan += new Wormhole.Engine.Player.Player.TookMulliganDelegate(Player_TookMulligan);

			this.Game.Player1.Team.CardAssigned += new Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard.CardAssignedDelegate(Team_CardAssigned);
			this.Game.Player1.UnassignedSupport.CardAssigned += new Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard.CardAssignedDelegate(UnassignedSupport_CardAssigned);

			this.Game.Player1.CardsInHand.CardPlayed += new Wormhole.Engine.Decks.HandCards.CardPlayedDelegate(CardsInHand_CardPlayed);

			this.Game.Mission.GlyphAssigned += new Wormhole.Engine.Mission.Mission.GlyphAssignedDelegate(Mission_GlyphAssigned);
			this.Game.Mission.ReplaceMissionBottom += new Wormhole.Engine.Mission.CardActionDelegate(Mission_ReplaceMissionBottom);

			this.Game.AskOpponentMulligan += new Wormhole.Engine.Game.GameActionDelegate(Game_AskOpponentMulligan);
		}
		#endregion

		#region Initialize Channel Events
		/// <summary>
		/// Wire up the events for the communications channel.
		/// </summary>
		protected override void InitialzeChannelEvents()
		{

		}
		#endregion

		#region Event Handlers

		#region Action Completed
		private void GameTurn_ActionCompleted(Wormhole.Engine.Turn.GameTurnAction action)
		{
			// only the hero player should send the notification
			if (this.Game.Player1 == this.Game.GameTurn.HeroPlayer)
				this.SendGameTurnAction(action);
			else if (action == Wormhole.Engine.Turn.GameTurnAction.Pass)
				this.SendGameTurnAction(action);
		}
		#endregion

		#region Kept Hand
		/// <summary>
		/// Kept Game_AskOpponentMulligan
		/// </summary>
		private void Player_KeptHand()
		{
			this.Channel.KeepHand();
		}
		#endregion

		#region Took Mulligan
		/// <summary>
		/// Took Mulligan
		/// </summary>
		private void Player_TookMulligan()
		{
			this.Channel.TakeMulligan();
		}
		#endregion

		#region Team Assigned
		/// <summary>
		/// Dipatch an a message when a team member is assigned.
		/// </summary>
		/// <param name="card"></param>
		private void Team_CardAssigned(Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard card)
		{
			this.Assign(card);
		}
		#endregion

		#region Support Assigned
		/// <summary>
		/// Dispatch a message when a support card is assigned.
		/// </summary>
		/// <param name="card"></param>
		private void UnassignedSupport_CardAssigned(Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard card)
		{
			this.Assign(card);
		}
		#endregion

		#region Card Played
		/// <summary>
		/// Handle the card played event
		/// </summary>
		/// <param name="card"></param>
		private void CardsInHand_CardPlayed(Wormhole.Engine.CardLibrary.BaseCardTypes.Card card)
		{
			this.PlayCard(card);
		}
		#endregion

		#region Glyph Assigned
		/// <summary>
		/// The glyph assigned event handler
		/// </summary>
		/// <param name="character"></param>
		private void Mission_GlyphAssigned(Wormhole.Engine.CardLibrary.CardTypes.Character character)
		{
			// only the hero player should send the notification
			if (this.Game.Player1 == this.Game.GameTurn.HeroPlayer)
				this.AssignMissionGlyph(character);
		}
		#endregion

		#region Replace Mission Bottom
		/// <summary>
		/// The replace mission bottom event handler.
		/// </summary>
		/// <param name="card">The mission which was replaced on the bottom of the mission pile.</param>
		private void Mission_ReplaceMissionBottom(Wormhole.Engine.CardLibrary.BaseCardTypes.Card card)
		{
			// only the hero player should send the notification
			if (this.Game.Player1 == this.Game.GameTurn.HeroPlayer)
				this.ReplaceMissionBottom(card);
		}
		#endregion

		#region Ask Opponent Mulligan
		/// <summary>
		/// Ask the opponent to take a mulligan or not.
		/// </summary>
		private void Game_AskOpponentMulligan()
		{
			this.SendGameTurnAction(Wormhole.Engine.Turn.GameTurnAction.AskMulligan);
		}
		#endregion

		#endregion

		#region Assign
		/// <summary>
		/// Dispatch a message that a card has been assigned.
		/// </summary>
		/// <param name="card">The card that was assigned.</param>
		private void Assign(Wormhole.Engine.CardLibrary.BaseCardTypes.SkillsCard card)
		{
			// create the action
			Action.CardAction cardAction = new Wormhole.Engine.Communication.Action.CardAction();
			cardAction.CardID = card.ID;
			cardAction.Action = Action.CardActionType.Assign;

			// dispatch the message
			this.Channel.PerformCardAction(cardAction);
		}
		#endregion

		#region Play Card
		/// <summary>
		/// Notify the opponent that a card was played.
		/// </summary>
		/// <param name="card">The card that was played.</param>
		private void PlayCard(Wormhole.Engine.CardLibrary.BaseCardTypes.Card card)
		{
			// create the action
			Action.CardAction cardAction = new Wormhole.Engine.Communication.Action.CardAction();
			cardAction.CardID = card.ID;
			cardAction.Action = Action.CardActionType.Play;

			// dispatch the message
			this.Channel.PerformCardAction(cardAction);
		}
		#endregion

		#region Send Game Turn Action
		/// <summary>
		/// Send a notification about a game turn action.
		/// </summary>
		/// <param name="action">The action</param>
		private void SendGameTurnAction(Wormhole.Engine.Turn.GameTurnAction turnAction)
		{
			// create the action
			Action.GameAction action = new Action.GameAction();
			action.Action = Action.GameActionType.GameTurnAction;
			action.Target = turnAction.ToString();

			// dispatch the message
			this.Channel.PerformGameAction(action);
		}
		#endregion

		#region Assign Mission Glyph
		/// <summary>
		/// Notify the opponent that the mission glyph was assigned to a card.
		/// </summary>
		/// <param name="card">The card the glyp was assigned to.</param>
		private void AssignMissionGlyph(Wormhole.Engine.CardLibrary.BaseCardTypes.Card card)
		{
			// create the action
			Action.CardAction cardAction = new Wormhole.Engine.Communication.Action.CardAction();
			cardAction.CardID = card.ID;
			cardAction.Action = Action.CardActionType.AssignMissionGlyph;

			// dispatch the message
			this.Channel.PerformCardAction(cardAction);
		}
		#endregion

		#region Replace Mission Bottom
		/// <summary>
		/// Send the notification that a mission was returned to the bottom of the mission pile.
		/// </summary>
		/// <param name="card">The mission card.</param>
		private void ReplaceMissionBottom(Wormhole.Engine.CardLibrary.BaseCardTypes.Card card)
		{
			// create the action
			Action.CardAction cardAction = new Wormhole.Engine.Communication.Action.CardAction();
			cardAction.CardID = card.ID;
			cardAction.Action = Action.CardActionType.ReplaceMissionBottom;

			// dispatch the message
			this.Channel.PerformCardAction(cardAction);
		}
		#endregion
	}
}
